// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.butler.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.ButlerBusinessTypeEnum;
import com.liuxinlong.enums.ButlerContentTypeEnum;
import com.liuxinlong.enums.MessageContentTypeEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.butler.service.ButlerService;
import com.liuxinlong.modules.common.entity.CommonSelectDto;
import com.liuxinlong.modules.common.service.CommonSelectService;
import com.liuxinlong.modules.dao.*;
import com.liuxinlong.modules.entity.BrowseRecord;
import com.liuxinlong.modules.entity.ButlerTrain;
import com.liuxinlong.modules.entity.MessageConfiguration;
import com.liuxinlong.modules.entity.QuestionAnswer;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.IPUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 智能管家培训业务接口层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022-09-27
 */
@Service
@Slf4j
public class ButlerServiceImpl implements ButlerService {
    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private ButlerTrainDao butlerTrainDao;

    @Autowired
    private FileManageDao fileManageDao;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private MessageDao messageDao;

    @Autowired
    private CommonSelectService commonSelectService;

    @Autowired
    private QuestionAnswerDao questionAnswerDao;

    @Autowired
    private ExpertDao expertDao;

    @Autowired
    private UserBrowseRecordDao userBrowseRecordDao;

    @Override
    public List<Map<String, Object>> pageTrainInfo(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<ButlerTrain> originalList = butlerTrainDao.pageTrainInfo(queryParam);
        List<Map<String, Object>> resultList = completeResult(originalList, startNum);
        return resultList;
    }

    @Override
    public int getTrainInfoCount(Map<String, Object> queryParam) {
        return butlerTrainDao.getTrainInfoCount(queryParam);
    }

    @Override
    @Transactional
    public void addTrainInfo(ButlerTrain butlerTrain, int forceFlag) {
        int showIndex = butlerTrain.getShowIndex();
        if (showIndex != 9999) {
            ButlerTrain indexData = butlerTrainDao.selectByIndex(butlerTrain.getBusinessType(),
                    butlerTrain.getSubType(), showIndex);
            if (!ObjectUtils.isEmpty(indexData) && !StringUtils.equals(butlerTrain.getId(), indexData.getId())) {
                if (forceFlag == 0) {
                    throw new AosException(ReturnCodes.HTTP_SAME_SERIAL_NUMBER, "当前排序位置已存在数据！");
                }
                indexData.setShowIndex(9999);
                butlerTrainDao.updateById(indexData);
            }
        }
        String id = SnowFlake.nextIdStr();
        butlerTrain.setId(id);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        butlerTrain.setCreateUser(currentUser.getId());
        butlerTrainDao.insert(butlerTrain);
        String newFileIds = StringUtils.isEmpty(butlerTrain.getCover()) ? butlerTrain.getMainFile() :
                (butlerTrain.getCover() + (StringUtils.isEmpty(butlerTrain.getMainFile()) ? "" :
                        "," + butlerTrain.getMainFile()));
        String allFileIds = StringUtils.isEmpty(newFileIds) ? butlerTrain.getMainFilePdf() :
                (newFileIds + (StringUtils.isEmpty(butlerTrain.getMainFilePdf()) ? "" :
                        "," + butlerTrain.getMainFilePdf()));
        fileManageService.updateBusinessFile(allFileIds, id);
    }

    @Override
    public void updateTrainInfo(ButlerTrain butlerTrain, int forceFlag) {
        String id = butlerTrain.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改培训文档信息失败，培训文档信息不存在！");
        }
        ButlerTrain oldInfo = butlerTrainDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改培训文档信息失败，培训文档信息不存在！");
        }
        int showIndex = butlerTrain.getShowIndex();
        if (showIndex != 9999) {
            ButlerTrain indexData = butlerTrainDao.selectByIndex(butlerTrain.getBusinessType(),
                    butlerTrain.getSubType(), showIndex);
            if (!ObjectUtils.isEmpty(indexData) && !StringUtils.equals(butlerTrain.getId(), indexData.getId())) {
                if (forceFlag == 0) {
                    throw new AosException(ReturnCodes.HTTP_SAME_SERIAL_NUMBER, "当前排序位置已存在数据！");
                }
                indexData.setShowIndex(9999);
                butlerTrainDao.updateById(indexData);
            }
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        butlerTrain.setUpdateUser(currentUser.getId());
        butlerTrain.setHeat(oldInfo.getHeat());
        butlerTrainDao.updateById(butlerTrain);
        if (StringUtils.equals(oldInfo.getCover(),
                butlerTrain.getCover()) && StringUtils.equals(oldInfo.getMainFile(),
                butlerTrain.getMainFile()) && StringUtils.equals(oldInfo.getMainFilePdf(),
                butlerTrain.getMainFilePdf())) {
            return;
        }
//        fileManageService.batchInvalidFile(id);
//        fileManageService.updateBusinessFile(butlerTrain.getCover(), id);
        String newFileIds = StringUtils.isEmpty(butlerTrain.getCover()) ? butlerTrain.getMainFile() :
                (butlerTrain.getCover() + (StringUtils.isEmpty(butlerTrain.getMainFile()) ? "" :
                        "," + butlerTrain.getMainFile()));
        String allFileIds = StringUtils.isEmpty(newFileIds) ? butlerTrain.getMainFilePdf() :
                (newFileIds + (StringUtils.isEmpty(butlerTrain.getMainFilePdf()) ? "" :
                        "," + butlerTrain.getMainFilePdf()));
        fileManageService.updateBusinessFile(allFileIds, id);
    }

    @Override
    public void deleteTrainInfo(String id) {
        butlerTrainDao.deleteById(id);
        fileManageService.batchInvalidFile(id);
    }

    @Override
    public void exportTrainInfo(String id, HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("培训文档导出excel.xlsx");
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        List<ButlerTrain> butlerTrainList = butlerTrainDao.pageTrainInfo(queryParam);
        String[] head = {"展示排序", "标题", "内容", "业务类型", "子业务类型", "内容类型", "状态", "主讲人/分享人", "时间"};
        data.setHead(head);
        String[][] dataList = new String[butlerTrainList.size()][head.length];
        int index = 0;
        for (ButlerTrain butlerTrain : butlerTrainList) {
            dataList[index][0] = String.valueOf(butlerTrain.getShowIndex());
            dataList[index][1] = butlerTrain.getTitle();
            dataList[index][2] = butlerTrain.getContent();
            dataList[index][3] = ButlerBusinessTypeEnum.getNameByValue(butlerTrain.getBusinessType());
            String subTypeName;
            if (butlerTrain.getSubType() == 0) {
                subTypeName = "-";
            } else {
                List<CommonSelectDto> subList = commonSelectService.queryTrainSubSelect(String.valueOf(butlerTrain.getBusinessType()));
                List<CommonSelectDto> subSelect = subList.stream().filter(subItem -> StringUtils.equals(subItem.getId(), String.valueOf(butlerTrain.getSubType()))).collect(Collectors.toList());
                if (!subSelect.isEmpty()) {
                    subTypeName = subSelect.get(0).getName();
                } else {
                    subTypeName = "-";
                }
            }
            dataList[index][4] = subTypeName;
            dataList[index][5] = ButlerContentTypeEnum.getNameByValue(butlerTrain.getContentType());
            dataList[index][6] = butlerTrain.getStatus() == 1 ? "启用" : "未启用";
            dataList[index][7] = butlerTrain.getShareUser();
            dataList[index][8] = StringUtils.isEmpty(butlerTrain.getUpdateTime()) ? butlerTrain.getCreateTime() : butlerTrain.getUpdateTime();

            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public ImportResp importTrainInfo(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                ButlerTrain butlerTrain = covertToBean(record);
                return false;
//				try {
//					materialStandardDao.insert(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetCode(ReturnCodes.HTTP_SUCCESS.getRetCode());
                resp.setRetMessage("导入物料替换数据部分失败，总数=" + resp.getTotal() + ",失败总数=" +
                        resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入物料替换数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    if (StringUtils.isEmpty(failRecord[3]) ||
                            StringUtils.equals(failRecord[3].trim(), "其他") ||
                            StringUtils.isEmpty(failRecord[9])) {
                        continue;
                    }
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("standardSn", failRecord[1]);
                    item.put("name", failRecord[2]);
                    item.put("standardType", StringUtils.equals(failRecord[3].trim(), "设计标准") ? 1 :
                            StringUtils.equals(failRecord[3].trim(), "测试标准") ? 2 : 3);
                    item.put("reviewDepartment", StringUtils.isNotEmpty(failRecord[4]) ?
                            failRecord[4].trim() : "");
                    item.put("hierarchy", failRecord[5]);
                    item.put("classification", failRecord[6]);
                    item.put("mandatory", StringUtils.equals(failRecord[7].trim(), "强制") ? 1 :
                            StringUtils.equals(failRecord[7].trim(), "推荐") ? 2 : 3);
                    item.put("version", failRecord[8]);
                    item.put("securityLevel", StringUtils.equals(failRecord[9].trim(), "A") ? 1 : 2);
                    item.put("applicability", failRecord[10]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    public ImportResp batchAddTrainInfo(List<ButlerTrain> dataList) {
//        Map<String, Map<String, String>> standardSnMap = questionAnswerDao.getStandardSnMap();
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        List<Map> failedList = new ArrayList<>();
        boolean insertSuccess;
        int sort = 1;
        for (ButlerTrain butlerTrain : dataList) {
            String message = "";
//            if (standardSnMap.size() > 0 && standardSnMap.containsKey(standard.getStandardSn())) {
//                message = "标准编号已存在";
//                insertSuccess = false;
//            } else {
            String id = SnowFlake.nextIdStr();
            butlerTrain.setId(id);
            butlerTrain.setCreateUser(currentUser.getId());
            try {
                butlerTrainDao.insert(butlerTrain);
                insertSuccess = true;
            } catch (Exception e) {
                insertSuccess = false;
                message = e.getMessage();
            }
//            }
            if (!insertSuccess) {
                Map<String, Object> map = ObjectUtils.object2Map(butlerTrain);
                map.put("sort", sort);
                map.put("message", message);
                sort++;
                failedList.add(map);
            }
        }
        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() :
                ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setFailedList(failedList);
        resp.setRetMessage(failedList.size() > 0 ? "导入培训文档信息部分成功" : "导入培训文档信息成功");
        return resp;
    }

    @Override
    public void updateTrainInfoStatus(String id, int pushFlag) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        ButlerTrain butlerTrain = butlerTrainDao.selectById(id);
        if (ObjectUtils.isEmpty(butlerTrain)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "培训文档不存在");
        }
        String currenTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        butlerTrain.setStatus(butlerTrain.getStatus() == 0 ? 1 : 0);
        butlerTrain.setUpdateUser(currentUser.getId());
        butlerTrain.setUpdateTime(currenTime);
        butlerTrainDao.updateById(butlerTrain);
        User current = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (pushFlag == 1) {
            MessageConfiguration mc = new MessageConfiguration();
            mc.setId(SnowFlake.nextIdStr());
            mc.setBusinessType(butlerTrain.getBusinessType() + 2);
            mc.setBusinessId(id);
            mc.setTitle(butlerTrain.getTitle());
            mc.setCreateUser(current.getId());
            String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
            mc.setCreateTime(currentTime);
            mc.setPushType(2);
            mc.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
            mc.setContent(butlerTrain.getTitle());
            mc.setShareUser(butlerTrain.getShareUser());
            mc.setTarget("3");
            messageDao.insert(mc);
        }
    }

    @Override
    @Transactional
    public void countClick(String id) {
        ButlerTrain butlerTrain = butlerTrainDao.selectById(id);
        if (ObjectUtils.isEmpty(butlerTrain)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "培训文档信息不存在！");
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        String currentDate = currentTime.substring(0, 10);
        BrowseRecord browseRecord = userBrowseRecordDao.getUserBrowseRecord(butlerTrain.getId(), currentUser.getId(), currentDate);
        if (!ObjectUtils.isEmpty(browseRecord)) {
            log.info("用户当日已点击，不统计浏览量");
            return;
        }
        butlerTrain.setHeat(butlerTrain.getHeat() + 1);
        butlerTrainDao.updateById(butlerTrain);
        BrowseRecord newBrowseRecord = new BrowseRecord();
        newBrowseRecord.setId(SnowFlake.nextIdStr());
        newBrowseRecord.setBusinessId(butlerTrain.getId());
        newBrowseRecord.setBrowseUser(currentUser.getId());
        newBrowseRecord.setBrowseTime(currentTime);
        userBrowseRecordDao.insert(newBrowseRecord);
    }

    @Override
    public Map<String, Object> queryTrainInfo(String id) {
        ButlerTrain butlerTrain = butlerTrainDao.selectById(id);
        Map<String, Object> resultMap;
        if (ObjectUtils.isEmpty(butlerTrain)) {
            QuestionAnswer questionAnswer = questionAnswerDao.selectById(id);
            if (ObjectUtils.isEmpty(questionAnswer)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "文件不存在！");
            }
            resultMap = ObjectUtils.object2Map(questionAnswer);
            resultMap.put("businessType", 1);
        } else {
            resultMap = ObjectUtils.object2Map(butlerTrain);
            Map<String, Object> queryParam = new HashMap<>();
            queryParam.put("parentId", id);
            User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
            queryParam.put("currentUser", currentUser.getId());
            int commentCount = commentDao.getCommentCount(queryParam);
            resultMap.put("commentCount", commentCount);
//            if (butlerTrain.getBusinessType() == ButlerBusinessTypeEnum.EXPERT.getValue()) {
//                Map<String, Map<String, String>> expertMap = expertDao.getExpertMap();
//                List<String> expertIdList = Arrays.asList(butlerTrain.getShareUser().split(","));
//                List<String> expertNameList = new ArrayList<>(expertIdList.size());
//                for (String expertId : expertIdList) {
//                    expertNameList.add(expertMap.containsKey(expertId) ? expertMap.get(expertId).get("name") : expertId);
//                }
//                resultMap.put("expertName", StringUtils.strip(expertNameList.toString(), "[]"));
//            }
        }
        return resultMap;
    }


    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private ButlerTrain covertToBean(String[] record) {
        ButlerTrain butlerTrain = new ButlerTrain();
        butlerTrain.setTitle(record[1].trim());
        butlerTrain.setCover(record[2].trim());
//        butlerTrain.setShowIndex(Integer.parseInt(record[3].trim()));
        butlerTrain.setContent(record[4].trim());
        return butlerTrain;

    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("设计编号不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 20) {
                addRowError("设计编号长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("设计名称不能为空", rowErrors);
        } else {
            if (record[2].trim().length() > 100) {
                addRowError("设计名称长度不能超过100", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("兼容性不能为空", rowErrors);
        } else {

            if (record[2].trim().length() > 100) {
                addRowError("兼容性字段非法", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[4].trim())) {
            addRowError("回顾部门不能为空", rowErrors);
        } else {
            if (record[4].trim().length() > 20) {
                addRowError("回顾部门长度不能超过20", rowErrors);
            }
        }
        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 补全数据
     *
     * @param originalList 原始数据
     * @param startNum     数据起始值
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<ButlerTrain> originalList, int startNum) {
        Set<String> fileList = originalList.stream().map(ButlerTrain::getCover).collect(Collectors.toSet());
        Map<String, Map<String, Object>> fileMap;
        if (fileList.size() > 0) {
            fileMap = fileManageDao.getFileMapByIds(fileList);
        } else {
            fileMap = new HashMap<>();
        }
        String currentIp = IPUtils.getCurrentIp();
        Map<String, Map<String, String>> expertMap = expertDao.getExpertMap();
        List<Map<String, Object>> resultList = new ArrayList<>();
        int sort = startNum + 1;
        for (ButlerTrain butlerTrain : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(butlerTrain);
            item.put("sort", sort);
            Map<String, Object> coverInfo = fileMap.get(butlerTrain.getCover());
            if (ObjectUtils.isEmpty(coverInfo)) {
                item.put("coverPath", "");
            } else {
                item.put("coverPath", String.valueOf(coverInfo.get("path")).replace("upload",
                        "http:\\\\" + currentIp + ":8090\\preview\\upload"));
            }
            item.put("businessName", ButlerBusinessTypeEnum.getNameByValue(butlerTrain.getBusinessType()));
            if (butlerTrain.getSubType() == 0) {
                item.put("subTypeName", "-");
            } else {
                List<CommonSelectDto> subList = commonSelectService.queryTrainSubSelect(String.valueOf(butlerTrain.getBusinessType()));
                List<CommonSelectDto> subSelect = subList.stream().filter(subItem -> StringUtils.equals(subItem.getId(), String.valueOf(butlerTrain.getSubType()))).collect(Collectors.toList());
                if (!subSelect.isEmpty()) {
                    item.put("subTypeName", subSelect.get(0).getName());
                } else {
                    item.put("subTypeName", "-");
                }
            }
//            if (butlerTrain.getBusinessType() == ButlerBusinessTypeEnum.EXPERT.getValue()) {
//                if (StringUtils.isNotEmpty(butlerTrain.getShareUser())) {
//                    List<String> expertIdList = Arrays.asList(butlerTrain.getShareUser().split(","));
//                    List<String> expertNameList = new ArrayList<>(expertIdList.size());
//                    for (String expertId : expertIdList) {
//                        expertNameList.add(expertMap.containsKey(expertId) ? expertMap.get(expertId).get("name") : expertId);
//                    }
//                    item.put("expertName", StringUtils.strip(expertNameList.toString(), "[]"));
//                }
//            }
            resultList.add(item);
            sort++;
        }
        return resultList;
    }
}
